package com.frontend.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import reactor.core.publisher.Mono;

import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .authorizeExchange(exchanges -> exchanges
                        .pathMatchers("/public/**", "/login/**", "/oauth2/**", "/favicon.ico").permitAll()
                        .pathMatchers("/api/**").authenticated() // API路径需要认证
                        .anyExchange().authenticated()
                )
                .oauth2Login(withDefaults())
                .oauth2Client(withDefaults())
                .csrf().disable();

        return http.build();
    }











    // 在网关的SecurityConfig.java中
    @Bean
    public ReactiveJwtDecoder reactiveJwtDecoder() {
        // 使用正确的算法名称
        SecretKeySpec secretKeySpec = new SecretKeySpec(
                "my-secret-key-12345".getBytes(StandardCharsets.UTF_8),
                "HMACSHA256" // 正确的算法名称
        );

        NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder.withSecretKey(secretKeySpec)
                .macAlgorithm(org.springframework.security.oauth2.jose.jws.MacAlgorithm.HS256)
                .build();

        return token -> {
            System.out.println("Attempting to decode JWT token");
            try {
                return jwtDecoder.decode(token)
                        .doOnNext(jwt -> {
                            System.out.println("Successfully decoded JWT:");
                            System.out.println("  Headers: " + jwt.getHeaders());
                            System.out.println("  Claims: " + jwt.getClaims());
                            System.out.println("  Subject: " + jwt.getSubject());
                        })
                        .doOnError(error -> {
                            System.err.println("Failed to decode JWT: " + error.getClass().getName() + " - " + error.getMessage());
                            error.printStackTrace();
                        });
            } catch (Exception e) {
                System.err.println("Exception during JWT decoding: " + e.getMessage());
                e.printStackTrace();
                throw e;
            }
        };
    }










    @Bean
    public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
        return new ReactiveJwtAuthenticationConverterAdapter(new Converter<Jwt, AbstractAuthenticationToken>() {
            @Override
            public AbstractAuthenticationToken convert(Jwt jwt) {
                Collection<GrantedAuthority> authorities = extractAuthorities(jwt);
                String username = extractUsername(jwt);
                System.out.println("Extracted username: " + username);
                System.out.println("Extracted authorities: " + authorities);
                return new JwtAuthenticationToken(jwt, authorities, username);
            }

            private String extractUsername(Jwt jwt) {
                // 按优先级顺序提取用户名
                String username = jwt.getClaimAsString("user_name");
                if (username != null && !username.isEmpty()) {
                    return username;
                }

                username = jwt.getClaimAsString("preferred_username");
                if (username != null && !username.isEmpty()) {
                    return username;
                }

                return jwt.getSubject();
            }

            private Collection<GrantedAuthority> extractAuthorities(Jwt jwt) {
                // 从 authorities 声明中提取权限
                List<String> authorities = jwt.getClaimAsStringList("authorities");
                if (authorities != null && !authorities.isEmpty()) {
                    return authorities.stream()
                            .map(auth -> new SimpleGrantedAuthority("ROLE_" + auth))
                            .collect(Collectors.toList());
                }

                // 从 scope 声明中提取权限
                List<String> scopes = jwt.getClaimAsStringList("scope");
                if (scopes != null && !scopes.isEmpty()) {
                    return scopes.stream()
                            .map(scope -> new SimpleGrantedAuthority("SCOPE_" + scope))
                            .collect(Collectors.toList());
                }

                return Collections.emptyList();
            }
        });
    }
}
